package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.util.StringUtil;
import com.zzyl.base.PageResponse;
import com.zzyl.constant.CacheConstants;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.utils.MergeUtil;
import com.zzyl.utils.UserThreadLocal;
import com.zzyl.vo.DeviceDataGraphVo;
import com.zzyl.vo.DevicePropertyStatusVo;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import com.zzyl.vo.ThingModelPublishedVo;
import com.zzyl.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @Description DeviceServiceImpl
 * @Author Bafeii7
 * @Date 2025-05-19 16:37
 */
@Service
@Slf4j
public class DeviceServiceImpl implements DeviceService {

    @Autowired
    private Client client;

    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private DeviceMapper deviceMapper;

    @Override
    public void syncProductList() {
        // 设置请求参数
        QueryProductListRequest queryProductListRequest = new QueryProductListRequest();
        queryProductListRequest.setCurrentPage(1);
        queryProductListRequest.setPageSize(200);
        queryProductListRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        // 调用阿里云的查询产品列表接口
        QueryProductListResponse response = null;
        try {
            response = client.queryProductList(queryProductListRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }

        // 判断接口是否调通
        if (!response.getBody().getSuccess()){
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

        // 获取数据，存入redis
        List<ProductVo> productVoList = response.getBody().getData().getList().getProductInfo()
                .stream().map(p -> BeanUtil.toBean(p,ProductVo.class)).collect(Collectors.toList());
        redisTemplate.opsForValue().set(CacheConstants.ALL_PRODUCT_KEY, JSONUtil.toJsonStr(productVoList));

    }

    @Override
    public List<ProductVo> allProductList() {
        String productListJsonStr  = redisTemplate.opsForValue().get(CacheConstants.ALL_PRODUCT_KEY);
        if (StringUtil.isEmpty(productListJsonStr)){
            throw  new BaseException(BasicEnum.IOT_LIST_PRODUCT_ERROR);
        }
        List<ProductVo> productVoList = JSONUtil.toList(productListJsonStr, ProductVo.class);
        return productVoList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void registerDevice(DeviceDto deviceDto) {
        // 首先检验设备名称是否重复，阿里云要求设备名称唯一
        Long deviceNameCount = deviceMapper.countByDeviceName(deviceDto.getDeviceName());
        if (deviceNameCount > 0){
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }

        // 调用阿里云新增设备接口
        RegisterDeviceRequest registerDeviceRequest = deviceDto.getRegisterDeviceRequest();
        registerDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        RegisterDeviceResponse registerDeviceResponse = null;
        try {
            registerDeviceResponse = client.registerDevice(registerDeviceRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
        // 查看是否调度接口成功
        if (!registerDeviceResponse.getBody().getSuccess()){
            throw new RuntimeException(registerDeviceResponse.getBody().getErrorMessage());
        }
        // 调用阿里云接口获得产品名称
        QueryProductRequest queryProductRequest = new QueryProductRequest();
        queryProductRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        queryProductRequest.setProductKey(deviceDto.getProductKey());
        QueryProductResponse queryProductResponse = null;
        try {
           queryProductResponse = client.queryProduct(queryProductRequest);

        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);
        }
        // 查看是否调度成功
        if (!queryProductResponse.getBody().getSuccess()){
            throw new RuntimeException(queryProductResponse.getBody().getErrorMessage());
        }
        String productName = queryProductResponse.getBody().getData().getProductName();
        // 封装pojo插入数据库
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        if (device.getLocationType() == 0){
            device.setPhysicalLocationType(-1);
        }
        device.setIotId(registerDeviceResponse.getBody().getData().getIotId());
        device.setProductName(productName);
        device.setHaveEntranceGuard(0);
        deviceMapper.insert(device);
    }

    @Override
    public PageResponse<DeviceVo> pageQueryDevice(DevicePageQueryDto devicePageQueryDto) {
        // 调用分页助手
        PageHelper.startPage(devicePageQueryDto.getPageNum(),devicePageQueryDto.getPageSize());
        Device device = BeanUtil.toBean(devicePageQueryDto, Device.class);
        // 查询获得数据
        Page<DeviceVo> page = deviceMapper.pageQueryDevice(device);
        return PageResponse.of(page,DeviceVo.class);
    }

    @Override
    public DeviceVo queryDeviceDetail(DeviceDto deviceDto) {
        QueryDeviceDetailRequest queryDeviceDetailRequest = new QueryDeviceDetailRequest();
        queryDeviceDetailRequest.setIotId(deviceDto.getIotId());
        queryDeviceDetailRequest.setProductKey(deviceDto.getProductKey());
        queryDeviceDetailRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        // 判断接口是否调度成功
            QueryDeviceDetailResponse queryDeviceDetailResponse = null;
            try {
                queryDeviceDetailResponse = client.queryDeviceDetail(queryDeviceDetailRequest);
            } catch (Exception e){
                throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_DETAIL_FAIL);
            }
            if (!queryDeviceDetailResponse.getBody().getSuccess()){
                throw new RuntimeException(queryDeviceDetailResponse.getBody().getErrorMessage());
            }

        // 将接口返回的内容封装到DeviceVo
        DeviceVo deviceVo = BeanUtil.toBean(queryDeviceDetailResponse.getBody().getData(), DeviceVo.class);
        // 查询数据库当中该设备的详细信息
        DeviceVo dbDeviceVo = deviceMapper.queryDeviceDetail(deviceVo.getIotId());
        // 判断数据库当中是否存在该设备
        if (ObjectUtil.isEmpty(dbDeviceVo)){
            throw new BaseException(BasicEnum.DEVICE_NOT_EXIST);
        }
        // 合并属性,调用工具类
        MergeUtil.mergeAllowOverride(dbDeviceVo,deviceVo);
        return deviceVo;
    }

    @Override
    public ThingModelPublishedVo queryThingModelPublished(QueryThingModelPublishedRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        // 调用阿里云接口查看指定产品的已发布物模型中的功能定义详情
        QueryThingModelPublishedResponse response = null;
        try {
            response = client.queryThingModelPublished(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }
        // 判断是否调度成功
        if (!response.getBody().getSuccess()){
            throw new RuntimeException(response.getBody().getErrorMessage());
        }
        // 封装对象
        ThingModelPublishedVo thingModelPublishedVo = new ThingModelPublishedVo();
        thingModelPublishedVo.setThingModelJson(response.getBody().getData().getThingModelJson());
        return thingModelPublishedVo;
    }

    @Override
    public DevicePropertyStatusVo queryDevicePropertyStatus(QueryDevicePropertyStatusRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        // 调用阿里云接口查询指定设备的物模型运行状态
        QueryDevicePropertyStatusResponse response = null;
        try {
            response = client.queryDevicePropertyStatus(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }
        // 判断是否调度成功
        if (!response.getBody().getSuccess()){
            throw new RuntimeException(response.getBody().getErrorMessage());
        }
        // 封装对象返回
//        QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyDataList list = response.getBody().getData().getList();
        DevicePropertyStatusVo devicePropertyStatusVo = new DevicePropertyStatusVo();
        devicePropertyStatusVo.setList(response.getBody().getData().getList());
        return devicePropertyStatusVo;
    }

    @Override
    public void batchUpdateDeviceNickname(DeviceDto deviceDto) {
        // 判断数据库是否拥有该设备
        if (ObjectUtil.isEmpty(deviceMapper.existDeviceById(deviceDto.getIotId()))){
            throw new BaseException(BasicEnum.DEVICE_NOT_EXIST);
        }
        // 封装参数
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        String subject = UserThreadLocal.getSubject();
        UserVo userVo = JSONUtil.toBean(subject, UserVo.class);
        Long userId = userVo.getId();
        //如果是随身设备，物理位置设为-1
        if (device.getLocationType() == 1 ) {
            device.setPhysicalLocationType(-1);
        }
        device.setUpdateBy(userId);
        // 更新数据库名称
        deviceMapper.updateByPrimaryKeySelective(device);
        // 封装请求参数
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo deviceNicknameInfo = new BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo();
        deviceNicknameInfo.setNickname(device.getNickname());
        deviceNicknameInfo.setIotId(device.getIotId());
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setDeviceNicknameInfo(Arrays.asList(deviceNicknameInfo));
        // 调用阿里云接口批量修改设备备注名称
        BatchUpdateDeviceNicknameResponse response = null;
        try {
            response = client.batchUpdateDeviceNickname(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }
        // 查看是否调度成功
        if (!response.getBody().getSuccess()){
            throw new RuntimeException(response.getBody().getErrorMessage());
        }
    }

    @Override
    public void deleteDevice(DeleteDeviceRequest request) {
        //  封装参数
        Device device = BeanUtil.toBean(request, Device.class);
        // 删除数据库设备
        deviceMapper.deleteByPrimaryKey(device.getIotId());
        // 设置删除参数
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        // 调用阿里云接口删除设备
        DeleteDeviceResponse response = null;
        try {
            response = client.deleteDevice(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
        // 判断是否删除成功
        if (!response.getBody().getSuccess()){
            throw new RuntimeException(response.getBody().getErrorMessage());
        }
    }


}
